// rk4_fixed.cpp 

/*
  Function to advance set of coupled first-order o.d.e.s by single step
  using fixed step-length fourth-order Runge-Kutta scheme

     x        ... independent variable
     y        ... array of dependent variables 
     h        ... fixed step-length

  Requires right-hand side routine
  
     void rhs_eval (double x, Array<double,1> y, Array<double,1>& dydx)
	
  which evaluates derivatives of y (w.r.t. x) in array dydx
*/

#include "mine.h"

void rk4_fixed (double& x, Array<double,1>& y, Array<double,1>& g, 
                void (*rhs_eval)(double, Array<double,1>, Array<double,1>, Array<double,1>&), 
                double h)
{
  // Array y assumed to be of extent n, where n is no. of coupled
  // equations
  int n = y.extent(0);

  // Declare local arrays
  Array<double,1> k1(n), k2(n), k3(n), k4(n), f(n), dydx(n);

  // Zeroth intermediate step 
  (*rhs_eval) (x, y, g, dydx);
  for (int j = 0; j < n; j++)
    {
      k1(j) = h * dydx(j);
      f(j) = y(j) + k1(j) / 2.;
    }

  // First intermediate step 
  (*rhs_eval) (x + h / 2., f, g, dydx);
  for (int j = 0; j < n; j++)
    {
      k2(j) = h * dydx(j);
      f(j) = y(j) + k2(j) / 2.;
    }

  // Second intermediate step
  (*rhs_eval) (x + h / 2., f, g, dydx);
  for (int j = 0; j < n; j++)
    {
      k3(j) = h * dydx(j);
      f(j) = y(j) + k3(j);
    }

  // Third intermediate step 
  (*rhs_eval) (x + h, f, g, dydx);
  for (int j = 0; j < n; j++)
    {
      k4(j) = h * dydx(j);
    }

  // Actual step 
  for (int j = 0; j < n; j++)
    {
      y(j) += k1(j) / 6. + k2(j) / 3. + k3(j) / 3. + k4(j) / 6.;
    }
  x += h;

  return;
}



